﻿
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows.Markup;
using UnityConfiguration.Infrastructure;
using System.Collections.Specialized;

namespace UnityConfiguration
{
    [ContentProperty("Items")]
    public class Unity
    {
        public const string ConfigurationKey = "UnityConfiguration";

        private List<IUnityItem> _Items;
        
        public TypeAliases TypeAliases {
            get { return this.Items.OfType<TypeAliases>().SingleOrDefault(); }
        }

        public Containers Containers {
            get {
                Containers containers = this.Items.OfType<Containers>().SingleOrDefault();
                containers.TypeResolver = new UnityTypeResolver(this.TypeAliases);
                return containers;
            }
        }

        public List<IUnityItem> Items {
            get { return _Items; }
            set { _Items = value; }
        }

        public Unity() {
            this.Items = new List<IUnityItem>();
        }

        public Container this[string containerName] {
            get { return this.Containers[containerName]; }
        }

        /// <summary>
        /// Creates a <see cref="Unity"/> from XAML.
        /// </summary>
        /// <param name="xamlStream"><see cref="Stream"/> that contains the XAML declaration of the catalog.</param>
        /// <returns>An instance of <see cref="Unity"/> built from the XAML.</returns>
        public static Unity CreateFromXaml(Stream xamlStream) {
            if (xamlStream == null) {
                throw new ArgumentNullException("xamlStream");
            }

#if SILVERLIGHT
            string xaml;
            using (System.IO.StreamReader reader = new System.IO.StreamReader(xamlStream)) {
                xaml = reader.ReadToEnd();
            }
            return XamlReader.Load(xaml) as Unity;
#else
            return XamlReader.Load(xamlStream) as Unity;
#endif
        }

        /// <summary>
        /// Creates a <see cref="Unity"/> from a XAML included as an Application Resource.
        /// </summary>
        /// <param name="builderResourceUri">Relative <see cref="Uri"/> that identifies the XAML included as an Application Resource.</param>
        /// <returns>An instance of <see cref="Unity"/> build from the XAML.</returns>
        public static Unity CreateFromXaml(Uri builderResourceUri) {
            var streamInfo = System.Windows.Application.GetResourceStream(builderResourceUri);

            if ((streamInfo != null) && (streamInfo.Stream != null)) {
                return CreateFromXaml(streamInfo.Stream);
            }

            return null;
        }
    }

    public class TypeAliases : ObservableCollection<TypeAlias>, IUnityItem
    {
        public TypeAliases() : base() { }

        public TypeAlias this[string alias] {
            get { return this.SingleOrDefault(a => a.Alias.Equals(alias)); }
        }
    }

    public class Containers : TypeResolvingCollection<Container>, IUnityItem
    {
        public Containers() : base() {
        }
        
        public Container this[string name] {
            get { return this.SingleOrDefault(c => c.Name == name); }
        }

        public Container Default {
            get { return this[string.Empty]; }
        }

    }

}
